/*
 * Elements.cpp
 *
 *  Created on: 2010-10-26
 *      Author: wenjian
 */

#include "Elements.h"
#include "Layer.h"

namespace Ed {
  Elements::Elements(){

  }
  Elements::Elements(AbstractElement* e):AbstractElements(e){
  }
  Elements::Elements(const std::vector<AbstractElement*>* es):AbstractElements(es){
  }
  Elements::Elements(const std::vector<Element*>* es)
    : AbstractElements((const std::vector<AbstractElement*>*)es){
  }
  Elements::~Elements() {

  }

  /**
   * 画此元素
   */
   void Elements::draw(Gdiplus::Graphics* g) {
     const vector<Element*>* els = getElements();
     vector<Element*>::const_iterator it = els->begin();
     for(; it != els->end(); it++){
       (*it)->draw(g);
     }
    setModified(false);
    setRedraw(false);
  }

  void Elements::redrawAll(const vector<AbstractElement*>* excludeds){
    if(!empty() && layer){
      Layer* gdiLayer = ((Layer*)getLayer());
      //清除绘图区
      vector<Element*> iv;
      vector<Element*> allExcludeds;
      if(excludeds){
        allExcludeds.insert(allExcludeds.end(), ((const vector<Element*>*)excludeds)->begin(), ((const vector<Element*>*)excludeds)->end());
        std::sort(allExcludeds.begin(), allExcludeds.end());
      }
      const std::vector<Element*>* els = getElements();
      for(std::vector<Element*>::const_iterator it = els->begin(); it!=els->end(); it++){
        Element* e = *it;
        //清除绘图区
        gdiLayer->unionDrawRegion(e->getBoundRect());
        //cout<<"Elements::redrawAll 2"<<endl;
        //返回与此元素所有相交的元素
        //gdiLayer->getIntersectionElements(&iv, e->getBoundRect(), &allExcludeds);
        gdiLayer->getIntersectionElements(&iv, e, &allExcludeds);
        if(!iv.empty()){
          //通知绘制相交元素,
          for(std::vector<Element*>::iterator iit = iv.begin(); iit!=iv.end(); iit++){
            (*iit)->setRedraw(true);
          }
          allExcludeds.insert(allExcludeds.end(), iv.begin(), iv.end());
          std::sort(allExcludeds.begin(), allExcludeds.end());
        }
        iv.clear();
      }
    }
  }

  /**
   * 增量移动到目标位置
   */
  void Elements::moveBy(real dx, real dy){
    if(empty() || !layer){
      return;
    }
    Layer* gdiLayer = ((Layer*)getLayer());

    //绘制与此组中元素相交的其它元素
    vector<Element*> iv;
    vector<Element*> allExcludeds;
    sort();
    const std::vector<Element*>* els = getElements();
    allExcludeds.insert(allExcludeds.end(), els->begin(), els->end());
    for(ConstIterator it = els->begin(); it!=els->end(); it++){
      Element* e = *it;
      //清除绘图区
      gdiLayer->unionDrawRegion(e->getBoundRect());

      //返回与此组中元素所有相交的元素
      //gdiLayer->getIntersectionElements(&iv, e->getBoundRect(), &allExcludeds);
      gdiLayer->getIntersectionElements(&iv, e, &allExcludeds);
      if(!iv.empty()){
        //通知绘制相交元素,
        for(Iterator iit = iv.begin(); iit!=iv.end(); iit++){
          (*iit)->setRedraw(true);
        }
        allExcludeds.insert(allExcludeds.end(), iv.begin(), iv.end());
        std::sort(allExcludeds.begin(), allExcludeds.end());
        iv.clear();
      }
    }

    //在目标区绘图
    for (ConstIterator it = els->begin(); it != els->end(); it++) {
      //重画此组中的元素
      (*it)->moveBy(dx, dy);
    }

    createBoundRect();
  }


  /**
   * 创建矩形区域
   */
  void Elements::createBoundRect(){
    real l=0.0, t=0.0, r=0.0, b=0.0;//左，上，右，下
    const std::vector<Element*>* els = getElements();
     if (!els->empty()) {
       const Gdiplus::RectF* firstRect = els->at(0)->getBoundRect();
       l = firstRect->GetLeft();
       t = firstRect->GetTop();
       r = firstRect->GetRight();
       b = firstRect->GetBottom();
       for (std::vector<Element*>::const_iterator it = els->begin()+1; it != els->end(); it++) {
         const Gdiplus::RectF* rect = (*it)->getBoundRect();
         l = l<rect->GetLeft()?l:rect->GetLeft();
         t = t<rect->GetTop()?t:rect->GetTop();
         r = r>rect->GetRight()?r:rect->GetRight();
         b = b>rect->GetBottom()?b:rect->GetBottom();
       }
     }
     _x = l;
     _y = t;
     _w = r-l;
     _h = b-t;
     Element::createBoundRect();
  }

}
